package com.ls.stack;


/**
 * 用数组实现栈
 */
public class ArrayStack {
    public static void main(String[] args) {
       /* ArrayStack arrayStack = new ArrayStack(4);

        arrayStack.push(10);
        arrayStack.push(20);
        arrayStack.push(30);
        arrayStack.push(40);
        arrayStack.show();*/

        String expression = "7-2*6-4";
        ArrayStack numStack = new ArrayStack(5);
        ArrayStack operStack = new ArrayStack(5);
        int index = 0;
        int num1 = 0;
        int num2 = 0;
        int oper = 0;
        int res = 0;
        char ch = ' ';
        String keepNum = "";
        while (true) {
            ch = expression.substring(index, index + 1).charAt(0);
            if (operStack.isOper(ch)) {
                if (!operStack.isEmpty()) {
                    if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {
//                    if (operStack.priority(ch) == 1) {
                        num2 = numStack.pop();
                        num1 = numStack.pop();
                        oper = operStack.pop();
                        res = operStack.calc(num1, num2, oper);
                        numStack.push(res);
                        operStack.push(ch);
                    } else {
                        operStack.push(ch);
                    }
                } else {
                    operStack.push(ch);
                }

            } else {
                keepNum += ch;
                if (index == expression.length() - 1) {
                    numStack.push(Integer.parseInt(keepNum));
                } else {
                    if (operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))) {
                        numStack.push(Integer.parseInt(keepNum));
                        keepNum = "";
                    }
                }

            }
            index++;
            if (index >= expression.length()) {
                break;
            }
        }
        //当表达式扫描完毕,就顺序的从两个栈中pop出相应的数和符号,并运行
        while (true) {
            if (operStack.isEmpty()) {
                break;
            }
            //这里是有问题的 应该从栈底开始运算
            num2 = numStack.pop();
            num1 = numStack.pop();
            oper = operStack.pop();
            res = operStack.calc(num1, num2, oper);
            numStack.push(res);
        }
        System.out.println(numStack.pop());


    }


    private int maxSize;//栈大小
    private int[] stack;
    private int top = -1;//栈顶

    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    public boolean isFull() {
        return top == maxSize - 1;
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public void push(int n) {
        if (isFull()) {
            System.out.println("full");
            return;
        }
        stack[++top] = n;

    }

    //查看栈顶值
    public int peek() {

        return stack[top];
    }


    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("empty");
        }
        return stack[top--];
    }

    public void show() {
        if (isEmpty()) {
            System.out.println("empty");
            return;
        }
        for (int i = top; i > -1; i--) {
            System.out.println(stack[i]);

        }
    }

    //----------

    /**
     * @param oper
     * @return 数字大优先级高
     */
    public int priority(int oper) {
        if (oper == '*' || oper == '/') {
            return 1;
        } else if (oper == '+' || oper == '-') {
            return 0;
        } else {
            return -1;
        }
    }

    public boolean isOper(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/';
    }

    private int calc(int num1, int num2, int oper) {

        int result = 0;

        switch (oper) {
            case '+':
                result = num1 + num2;
                break;
            case '-':
                result = num1 - num2;
                break;
            case '*':
                result = num1 * num2;
                break;
            case '/':
                result = num1 / num2;
                break;
            default:
                break;
        }


        return result;
    }
}
